package com.youboy.oauth;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import com.youboy.oauth.common.OAuthCodec;
import com.youboy.oauth.common.OAuthParameters;
import com.youboy.oauth.token.InvalidTokenException;
import com.youboy.oauth.token.OAuthToken;
import com.youboy.oauth.token.OAuthTokenService;
import com.youboy.oauth.verifier.OAuthTokenVerifierService;
import com.youboy.oauth.verifier.RandomOAuthTokenVerifierService;

/**
 * 
 * @author loudyn
 * 
 */
public class OAuthAuthorizeFilter implements Filter {
	private OAuthTokenService tokenService;
	private OAuthTokenVerifierService tokenVerifierService = new RandomOAuthTokenVerifierService();

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
	 * javax.servlet.FilterChain)
	 */
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

		String unauthorizedOAuthToken = null;
		String verifier = null;
		try {

			unauthorizedOAuthToken = request.getParameter(OAuthParameters.OAUTH_TOKEN.asString());
			verifier = getTokenVerifierService().createVerifier();
			getTokenService().authorizeRequestToken(unauthorizedOAuthToken, verifier);

			onValidOAuthAuthentication(unauthorizedOAuthToken, verifier, (HttpServletRequest) request, (HttpServletResponse) response);
		} catch (InvalidTokenException e) {
			onInvalidOAuthAuthentication((HttpServletRequest) request, (HttpServletResponse) response, e);
		}
	}

	/**
	 * 
	 * @param unauthorizedOAuthToken
	 * @param verifier
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	protected void onValidOAuthAuthentication(String unauthorizedOAuthToken, String verifier,
												HttpServletRequest request, HttpServletResponse response) throws IOException {

		sendRedirect(unauthorizedOAuthToken, verifier, response);
	}

	/**
	 * 
	 * @param request
	 * @param response
	 * @param e
	 * @throws IOException
	 */
	protected void onInvalidOAuthAuthentication(HttpServletRequest request,
												HttpServletResponse response,
												InvalidTokenException e) throws IOException {

		response.sendError(401, e.getMessage());
	}

	private void sendRedirect(String requestToken, String verifier, HttpServletResponse response) throws IOException {
		OAuthToken oauthToken = getTokenService().getOAuthToken(requestToken);
		String callbackUrl = oauthToken.getCallbackUrl();

		char appendChar = '?';
		if (StringUtils.indexOf(callbackUrl, "?") > 0) {
			appendChar = '&';
		}

		String redirectUrl = new StringBuilder().append(callbackUrl).append(appendChar).append(OAuthParameters.OAUTH_TOKEN.asString())
												.append("=").append(OAuthCodec.oauthEncode(requestToken))
												.append("&").append(OAuthParameters.OAUTH_VERIFIER)
												.append("=").append(OAuthCodec.oauthEncode(verifier))
												.toString();

		response.sendRedirect(redirectUrl);
	}

	@Override
	public void destroy() {
	}

	public OAuthTokenService getTokenService() {
		return tokenService;
	}

	public void setTokenService(OAuthTokenService tokenService) {
		this.tokenService = tokenService;
	}

	public OAuthTokenVerifierService getTokenVerifierService() {
		return tokenVerifierService;
	}

	public void setTokenVerifierService(OAuthTokenVerifierService tokenVerifierService) {
		this.tokenVerifierService = tokenVerifierService;
	}
}
